#ifndef __DEFAULTRAYTRACER__
#define __DEFAULTRAYTRACER__

#include "Tracer.h"
#include "Point3D.h"
#include "GeometricObjects.h"
#include <vector>
#include "Scene.h"
#include "Ray.h"
#include "BVH.h"
#include "ShadowRay.h"

/*==========================================================================
						Implementation of a Simple RayTracer
============================================================================*/

namespace Engine
{
	using std::vector;
	class DepthTracer : public Engine::Tracer
	{

	public:

		DepthTracer(Scene * p_scene, bool p_flatten = false, Engine::PartitioningStyle p_partitioningStyle = MIDDLE_POINT)
		{
			sceneObjects = p_scene;
			accelerationStructure = new BVH(sceneObjects->m_sceneObjects,p_partitioningStyle, p_flatten);
			accelerated = false;
		}


		DepthTracer()
		{}

		using Engine::Tracer::TraceRay;
		virtual bool TraceRay(Ray& ray, ShadeRec& rec, bool p_shadowRayTest = false)
		{
			double tmin = INT_MAX;
			rec.ray = ray;
			if (accelerated)
			{
				return accelerationStructure->TestIntersection(ray, rec, tmin, p_shadowRayTest);
			}
			else
			{
				if (p_shadowRayTest)
				{
					TraceShadowRay(ray.o, ray.d, rec);
				}
				else
				{
					return TraceRay(ray.o, ray.d, rec);
				}
				
			}//return TraceRay(ray.o, ray.d, rec);
		}

		bool TraceShadowRay(Point3D& o, Point3D& d, ShadeRec& rec)
		{
			double tmin = INT_MAX;
			RGBColor ouptutColor(0);
			bool tempHit = false;
			for (int index = 0; index < sceneObjects->m_sceneObjects.size(); index++)
			{
				GeometricObjects *currentGeometricObject = sceneObjects->m_sceneObjects[index];
				tempHit = currentGeometricObject->hit(o, d, tmin, rec);

				if (tempHit)
				{
					break;
				}
			}

			//retrun constant z 
			return rec.hitAnObject;
		}

		bool TraceRay(Point3D& o, Point3D& d, ShadeRec& rec)
		{
			double tmin = INT_MAX;
			RGBColor ouptutColor(0);
			bool tempHit = false;
			for (int index = 0; index < sceneObjects->m_sceneObjects.size(); index++)
			{
				GeometricObjects *currentGeometricObject = sceneObjects->m_sceneObjects[index];
				tempHit = currentGeometricObject->hit(o, d, tmin, rec);
			}

			//retrun constant z 
			return rec.hitAnObject;
		}
	};

}
#endif // !__DEFAULTRAYTRACER__
